<template>
    <el-select ref="moduleselect"
               placeholder="请选择"
               v-model="aVal"
               filterable
               reserve-keyword
               collapse-tags
               :popper-class="multiple?'modulemultiselect':'moduleselect'"
               :filter-method="fHandleData"
               :multiple="multiple"
               :title="sTitle"
               @visible-change="fResetOpts">
        <el-option label="handle"
                   value="handle"
                   v-if="multiple">
            <div class="moduleselect-btn"
                 @click.stop="fSelectAll('check')">全选</div>
            <div class="moduleselect-btn"
                 @click.stop="fSelectAll('cancel')">清空</div>
        </el-option>
        <el-option v-for="oItem in aOpts"
                   :class="{color:oItem.filter}"
                   :key="oItem[field[0]]"
                   :label="oItem[field[1]]"
                   :value="oItem[field[0]]">
        </el-option>
    </el-select>
</template>

<script>
    export default {
        props: {
            data: { //下拉选项
                type: Array
            },
            field: { //下拉选项字段
                type: Array,
                default: () => ['key', 'value']
            },
            multiple: { //默认多选
                type: Boolean,
                default: true
            },
            bind: { //表单验证的值，单选时 String，多选时 Array
                type: [String, Array]
            }
        },
        data() {
            return {
                aOpts: JSON.parse(JSON.stringify(this.data))
            }
        },
        computed: {
            //鼠标悬停时的提示
            sTitle() {
                let oData = {},
                    sVal;

                this.aOpts.forEach(oItem => { oData[oItem.key] = oItem.value; });
                if (Array.isArray(this.aVal)) {
                    sVal = this.aVal.reduce((sRes, sVal) => sRes + `${oData[sVal]};`, '');
                    return sVal.slice(0, sVal.length - 1);
                }
                else {
                    return oData[this.aVal];
                }
            },
            aVal: {
                get() {
                    if (this.multiple) {
                        return this.bind ? this.bind : [];
                    } else {
                        return this.bind;
                    }
                },
                set(data) {//接收 v-model 赋值时向外传递
                    this.$emit('update:bind', data);
                }
            }
        },
        methods: {
            //搜索时，将搜索出的数据标绿
            fHandleData(sVal) {
                if (sVal) {
                    this.aOpts.forEach((oItem, nIndex) => {
                        this.$set(this.aOpts, nIndex, {
                            ...oItem,
                            filter: oItem[this.field[1]].indexOf(sVal) > -1
                        });
                    });
                } else {
                    this.aOpts = JSON.parse(JSON.stringify(this.data));
                }
            },
            //全选、重置opts
            fSelectAll(sType) {
                let aData = [];
                switch (sType) {
                    case 'check':
                        aData = this.aOpts.reduce((aArr, oItem) => ([...aArr, oItem[this.field[0]]]), []);
                        break;
                    case 'cancel':
                        this.$refs.moduleselect.$children[0].$emit('input', '');
                        this.aOpts = JSON.parse(JSON.stringify(this.data));
                        break;
                }
                //this.$refs.moduleselect.focus() 不生效：el-select 源码中，focus 时聚焦 reference 未自动聚焦搜索文本框
                this.$refs.moduleselect.$refs.input.focus();
                this.$emit('update:bind', aData);
            },
            //下拉框隐藏时，重置opts
            fResetOpts(bVal) {
                bVal && (this.aOpts = JSON.parse(JSON.stringify(this.data)));
            }
        }
    }
</script>

<style lang="less" rel="stylesheet">
    //下拉模糊搜索（多选）
    .modulemultiselect {
        .l_noselect();
        .el-scrollbar {
            padding-top: 28px;
        }
        .el-select-dropdown__item:first-child {
            position: absolute;
            top: 0;
            width: 100%;
            display: flex;
            justify-content: space-between;
            padding: 0;
            background: #fff;
            border-bottom: 2px solid #f5f7fa;
            z-index: 999;
            cursor: auto;
            &.hover {
                background: #fff;
            }
            .moduleselect-btn {
                display: flex;
                flex: 1;
                justify-content: center;
                cursor: pointer;
            }
            .moduleselect-btn:hover {
                color: #409eff;
            }
            .moduleselect-btn:last-child {
                text-align: right;
            }
        }
        .el-select-dropdown__item.color {
            color: #67c23a;
            font-weight: bold;
        }
    }

    //下拉模糊搜索（单选）
    .moduleselect {
        .l_noselect();
        .el-select-dropdown__item.color {
            color: #67c23a;
            font-weight: bold;
        }
    }
</style>
